#define _CRT_SECURE_NO_WARNINGS 1

#include <iostream>
#include <vector>

using namespace std;

class UnionSearchSet
{
public:
    UnionSearchSet(int n) :_uss(n, -1)
    {}

    int FindRootIndex(int x)
    {
        int root = x;

        while (_uss[root] >= 0)
        {
            root = _uss[root];
        }

        while (_uss[x] >= 0)
        {
            int p = _uss[x];
            _uss[x] = root;
            x = p;
        }

        return root;
    }

    void Union(int x, int y)
    {
        int xr = FindRootIndex(x);
        int yr = FindRootIndex(y);

        if (xr == yr)
            return;

        _uss[xr] += _uss[yr];
        _uss[yr] = xr;
    }

    bool InSet(int x, int y)
    {
        return FindRootIndex(x) == FindRootIndex(y);
    }

    // ��ĳ������Ԫ�صĸ���
    int ElementNum(int x)
    {
        return -_uss[FindRootIndex(x)];
    }

    // �󼯺ϵĸ���
    int SetSize()
    {
        int count = 0;
        for (auto e : _uss)
        {
            if (e < 0) count++;
        }

        return count;
    }

private:
    std::vector<int> _uss;
};

// �ϲ�����
int main()
{
    int n;
    int m;
    cin >> n >> m;

    UnionSearchSet uss(n + 1);

    for (int i = 0; i < m; i++)
    {
        char str[2];
        int a;
        int b;

        cin >> str >> a >> b;

        if (str[0] == 'M')
        {
            uss.Union(a, b);
        }
        else
        {
            if (uss.InSet(a, b))
            {
                puts("Yes");
            }
            else
            {
                puts("No");
            }
        }
    }

    return 0;
}

// ��ͨ���е������
int main()
{
    int n; int m;

    scanf("%d%d", &n, &m);

    UnionSearchSet uss(n + 1);

    for (int i = 0; i < m; i++)
    {
        string str;
        cin >> str;

        int a;
        int b;

        if (str == "C")
        {
            cin >> a >> b;

            uss.Union(a, b);

        }
        else if (str == "Q1")
        {
            cin >> a >> b;
            if (uss.InSet(a, b))
            {
                puts("Yes");
            }
            else
            {
                puts("No");
            }
        }
        else
        {
            cin >> a;

            cout << uss.ElementNum(a) << endl;
        }
    }

    return 0;
}

// 等式方程的可满足性
class Solution {
public:
    bool equationsPossible(vector<string>& equations) {

        vector<int> uss(26,-1);

        auto Union=[&](int x,int y)mutable->void
        {
            int xr=x;   
            int yr=y;

            while(uss[xr]>=0) xr=uss[xr];
            while(uss[yr]>=0) yr=uss[yr];

            if(xr==yr) return;

            uss[xr]+=uss[yr];
            uss[yr]=xr;
        };
        
        auto IsInSet=[&](int x,int y)mutable->bool
        {
            int xr=x;   
            int yr=y;

            while(uss[xr]>=0) xr=uss[xr];
            while(uss[yr]>=0) yr=uss[yr];

            return xr==yr;
        };

        // 先将相等的元素合并到一个集合
        for(const string& str:equations)
        {
            if(str[1]=='=')
            {
                Union(str[0]-'a',str[3]-'a');
            }
        }

        // 再遍历一遍,进行不相等判断,如果两个应该不相等的元素在一个集合则不满足
        for(const string& str:equations)
        {
            if(str[1]=='!')
            {
                if(IsInSet(str[0]-'a',str[3]-'a'))
                {
                    return false;
                }
            }
        }

        return true;
    }
};